// Author: wsfuyibing <682805@qq.com>
// Date: 2025-06-24

package lock

import (
	"context"
	"gitee.com/go-libs/db-xorm/db"
	"server/app/errs"
	"server/app/http/models"
	"server/app/http/services"
	"server/app/kind"
	"server/app/lib/user_balance/operations"
	"sync"
)

var (
	once     = new(sync.Once)
	operator *Operator
)

// Operator
// 锁定余额.
//
// 销定(冻结)用户的指定金额, 被锁定的余额是不允许再消费的.
type Operator struct {
	operations.Operations
}

// New
// 获取单例.
func New() *Operator { return operator }

// Run
// 执行逻辑.
func (o *Operator) Run(ctx context.Context, sess *db.Session, uid kind.UserId, balance kind.Balance, bo kind.BalanceOperate, link kind.Link, params kind.LinkParams) (affects int64, err error) {
	var (
		has    bool
		latest *models.BalanceRecords
	)

	// 1. 忽略处理.
	//    不能冻结少于0.1元的余额.
	if balance.IsZero() {
		return
	}

	// 2. 读取流水.
	if latest, has, err = o.GetLatestRecord(ctx, sess, uid); err != nil {
		return
	} else if !has {
		err = errs.ErrUserBalanceNotEnough
		return
	}

	// 3. 对比余额.
	//    剩余可用的余额不足以冻结所需的的金额.
	if !latest.Balance.GreaterEqual(balance) {
		err = errs.ErrUserBalanceNotEnough
		return
	}

	// 4. 创建记录.
	record := &models.BalanceRecords{
		UserId:        uid,
		Balance:       0,
		Before:        0,
		Operate:       0,
		OperateType:   bo,
		OperateIncome: kind.BalanceIncomeNo,
		Link:          link,
		LinkParams:    params,
	}

	// 4.1 金额参数.
	record.Before = latest.Balance
	record.Operate = balance.Reverse()
	record.Balance = record.Before + record.Operate

	// 5. 设置余额.
	//    记录用户最后的余额.
	if err = o.SetUserBalance(ctx, sess, uid, record.Balance); err != nil {
		return
	}

	// 6. 计数累加.
	if err = o.SetUserFreezed(ctx, sess, uid, balance); err != nil {
		return
	}

	// 7. 添加流水.
	if _, err = services.NewBalanceRecordsService(sess).Dao.AddByStruct(ctx, record); err == nil {
		affects = 1
	}
	return
}

func init() {
	once.Do(func() {
		operator = &Operator{}
	})
}
